using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.IO;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using Mono.Addins;
using Common.Gui.GuiWinFormsLib.ExtensionNodes;
using Common.Interfaces;
using Common.Gui.GuiWinFormsLib.Descriptors;

namespace Common.Gui.GuiWinFormsLib
{
	/// <summary>
	/// main application form 
	/// </summary>
	public partial class MainForm : Form
	{
		DescriptorProvider provider;
		
		internal bool LazyResizing
		{
			get;
			set;
		}
		
		public MainForm()
		{
			InitializeComponent();
			
			this.provider = DescriptorProvider.GetInstance();
			this.provider.LoadDescriptors();
			
			try
			{
				this.provider.Apply("MainForm", this);
			}
			catch (Exception ex)
			{
				Logging.Logger.AddException(ex);
			}
			
			this.LazyResizing = false;
			
			this.SuspendLayout();

			BuildMenu();
			BuildToolbar();
			BuildPanels();
			BuildStatusbar();

			this.ResumeLayout();

			this.ResizeBegin += HandleResizeBegin;
			this.ResizeEnd += HandleResizeEnd;
			this.FormClosing += new FormClosingEventHandler(MainForm_FormClosing);
		}

		void HandleResizeEnd (object sender, EventArgs e)
		{
			if (this.LazyResizing)
			{
				this.ResumeLayout(true);
				this.dockingContainerBottom.ResumeLayout(true);
				this.dockingContainerLeft.ResumeLayout(true);
				this.dockingContainerRight.ResumeLayout(true);
				this.dockingContainerCenter.ResumeLayout(true);
			}
		}

		void HandleResizeBegin (object sender, EventArgs e)
		{
			if (LazyResizing)
			{
				this.SuspendLayout();
				this.dockingContainerBottom.SuspendLayout();
				this.dockingContainerLeft.SuspendLayout();
				this.dockingContainerRight.SuspendLayout();
				this.dockingContainerCenter.SuspendLayout();
			}
		}

		void MainForm_FormClosing(object sender, FormClosingEventArgs e)
		{
			ClearPanels();
			
			foreach (TypeExtensionNode node in Mono.Addins.AddinManager.GetExtensionNodes("/Common/Gui/GuiWinFormsLib/QuitCommand"))
			{
				try
				{
					ICommand command = (ICommand)node.CreateInstance();
					if (command != null)
					{
						command.Run();
					}
				}
				catch (Exception ex)
				{
					var addin = string.Empty;
					if (node.Addin != null)
					{
						addin = node.Addin.Id;
					}

					Logging.Logger.AddError("Exception while performing quit command from " + addin);
					Logging.Logger.AddException(ex);
				}
			}
		}

		/// <summary>
		/// clear all contianers from all dockable panels - panels will be disposed
		/// </summary>
		private void ClearPanels()
		{
			try
			{
				this.dockingContainerBottom.Clear();
				this.dockingContainerCenter.Clear();
				this.dockingContainerRight.Clear();
				this.dockingContainerLeft.Clear();
			}
			catch (Exception ex)
			{
				MessageBox.Show(ex.Message, "Exception while cleaning gui", MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
		}

		/// <summary>
		/// create dockable panels and put them in containers 
		/// </summary>
		private void BuildPanels ()
		{
			// clear everything first
			ClearPanels();
			
			var panels = AddinManager.GetExtensionNodes("/Common/Gui/GuiWinFormsLib/DockablePanel");
			foreach (AbstractDockablePanelNode node in panels)
			{
				IDockablePanel panel = node.GetDockablePanel();
				var panelControl = (panel as System.Windows.Forms.Control);

				if (panelControl != null)
				{
					Common.Gui.GuiWinFormsLib.Controls.DockingContainer targetContainer = null;

					switch (node.PanelLocation) 
					{
					case PanelLocation.Bottom:
						targetContainer = this.dockingContainerBottom;
						break;
					case PanelLocation.Center:
						targetContainer = this.dockingContainerCenter;
						break;
					case PanelLocation.Left:
						targetContainer = this.dockingContainerLeft;
						break;
					case PanelLocation.Right:
						targetContainer = this.dockingContainerRight;
						break;
					default:
						targetContainer = this.dockingContainerCenter;
					break;
					}

					targetContainer.Controls.Add(panelControl);
					targetContainer.Visible = true;
				}
			}
		}
		
		/// <summary>
		/// build form's main manu;
		/// hide it, if empty
		/// </summary>
		private void BuildMenu()
		{
			this.menuStrip2.Items.Clear();
			// Add the new buttons
			var menuItems = AddinManager.GetExtensionNodes("/Common/Gui/GuiWinFormsLib/MainMenu");
			foreach (MenuNode node in menuItems)
			{
				var menuNode = node.GetMenuItem();
				if (menuNode != null)
				{
					this.menuStrip2.Items.Add(menuNode);	
				}
			}


			if (menuItems.Count == 0)
				this.menuStrip2.Visible = false;
			else
				this.menuStrip2.Visible = true;
		}

		/// <summary>
		/// Buidl main form's toolbar;
		/// hide it if empty
		/// </summary>
		private void BuildToolbar()
		{   
			this.toolStrip1.Items.Clear();
			
			var registeredNodes = AddinManager.GetExtensionNodes("/Common/Gui/GuiWinFormsLib/ToolbarButtons");
			//Add the new buttons to the toolbar
			foreach (ToolBarNode node in registeredNodes)
			{
				var toolNode = node.GetToolItem();
				if (toolNode != null)
				{
					this.toolStrip1.Items.Add(toolNode);
				}
			}

			if (registeredNodes.Count == 0)
				this.toolStrip1.Visible = false;
			else
				this.toolStrip1.Visible = true;
		}

		private void BuildStatusbar()
		{
			// TODO there is currently no extension point for status bar
			// create one

			this.statusStrip1.Visible = false;
		}

		void OnExtensionChanged(object o, ExtensionEventArgs args)
		{
			if (args.PathChanged("/Common/Gui/GuiWinFormsLib/ToolbarButtons"))
			{
				BuildToolbar();
			}
			if (args.PathChanged("/Common/Gui/GuiWinFormsLib/MainMenu"))
			{
				BuildMenu();
			} 
			//TODO status bar

			Logging.Logger.AddImportant("Extesnsion changed: " + args.Path);
		}
	}
}
